package com.indi.gulimall.ware.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.indi.common.constant.WareConstant.PurchaseDetailEnum;
import com.indi.common.constant.WareConstant.PurchaseEnum;
import com.indi.common.enums.BizCodeEnum;
import com.indi.common.utils.PageUtils;
import com.indi.common.utils.Query;
import com.indi.common.utils.R;
import com.indi.gulimall.ware.dao.PurchaseDao;
import com.indi.gulimall.ware.entity.PurchaseDetailEntity;
import com.indi.gulimall.ware.entity.PurchaseEntity;
import com.indi.gulimall.ware.feign.ProductFeignService;
import com.indi.gulimall.ware.service.PurchaseDetailService;
import com.indi.gulimall.ware.service.PurchaseService;
import com.indi.gulimall.ware.service.WareSkuService;
import com.indi.gulimall.ware.vo.PurchaseDetailFinishVO;
import com.indi.gulimall.ware.vo.PurchaseFinishVO;
import com.indi.gulimall.ware.vo.PurchaseVO;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


@Service("purchaseService")
public class PurchaseServiceImpl extends ServiceImpl<PurchaseDao, PurchaseEntity> implements PurchaseService {
    @Resource
    private PurchaseDetailService purchaseDetailService;

    @Resource
    private WareSkuService wareSkuService;

    @Resource
    private ProductFeignService productFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(
                new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>()
        );

        return new PageUtils(page);
    }

    @Override
    public PageUtils getUnclaimedList(Map<String, Object> params) {
        IPage<PurchaseEntity> page = this.page(new Query<PurchaseEntity>().getPage(params),
                new QueryWrapper<PurchaseEntity>().between("status", 0, 1));
        return new PageUtils(page);
    }

    @Override
    public R mergePurchase(PurchaseVO purchaseVO) {
        Collection<PurchaseDetailEntity> purchaseDetailEntities = purchaseDetailService.listByIds(purchaseVO.getItems());
        for (PurchaseDetailEntity purchaseDetail : purchaseDetailEntities) {
            if (purchaseDetail.getStatus() != PurchaseDetailEnum.UNALLOCATED.getCode() &&
                    purchaseDetail.getStatus() != PurchaseDetailEnum.ASSIGNED.getCode()) {
                return R.error(BizCodeEnum.MERGE_PURCHASE_EXCEPTION);
            }
        }
        Long purchaseId = purchaseVO.getPurchaseId();
        if (purchaseId == null) {
            // 未指定任何采购单
            PurchaseEntity purchase = new PurchaseEntity();
            purchase.setStatus(PurchaseEnum.UNALLOCATED.getCode());
            this.save(purchase);
            purchaseId = purchase.getId();
        }

        Long finalPurchaseId = purchaseId;
        List<PurchaseDetailEntity> purchaseDetails = purchaseVO.getItems().stream().map(item -> {
            PurchaseDetailEntity purchaseDetail = new PurchaseDetailEntity();
            purchaseDetail.setId(item);
            purchaseDetail.setPurchaseId(finalPurchaseId);
            purchaseDetail.setStatus(PurchaseDetailEnum.ASSIGNED.getCode());
            return purchaseDetail;
        }).collect(Collectors.toList());

        purchaseDetailService.updateBatchById(purchaseDetails);
        return R.ok("合并成功");
    }

    @Override
    public void receivePurchase(List<Long> purchaseIds) {
        List<PurchaseEntity> purchases = purchaseIds.stream().map(purchaseId -> {
            PurchaseEntity purchase = this.getById(purchaseId);
            return purchase;
        }).filter(purchase -> {
            if (purchase.getStatus() == PurchaseEnum.UNALLOCATED.getCode() ||
                    purchase.getStatus() == PurchaseEnum.ASSIGNED.getCode()) {
                return true;
            }
            return false;
        }).map(item -> {
            PurchaseEntity purchase = new PurchaseEntity();
            purchase.setStatus(PurchaseEnum.RECEIVED.getCode());
            purchase.setId(item.getId());
            return purchase;
        }).collect(Collectors.toList());

        this.updateBatchById(purchases);

        List<PurchaseDetailEntity> purchaseDetails = purchaseDetailService.listByPurchaseIds(purchaseIds);
        List<PurchaseDetailEntity> purchaseDetailList = purchaseDetails.stream().map(item -> {
            PurchaseDetailEntity purchaseDetail = new PurchaseDetailEntity();
            purchaseDetail.setStatus(PurchaseDetailEnum.PURCHASING.getCode());
            purchaseDetail.setId(item.getId());
            return purchaseDetail;
        }).collect(Collectors.toList());

        purchaseDetailService.updateBatchById(purchaseDetailList);
    }

    @Override
    public void finishPurchase(PurchaseFinishVO purchaseFinishVO) {
        // 更新采购需求
        List<PurchaseDetailEntity> purchaseDetails = new ArrayList<>();
        boolean flag = true;
        for (PurchaseDetailFinishVO item : purchaseFinishVO.getItems()) {
            if (item.getStatus() == PurchaseDetailEnum.PURCHASE_FAILED.getCode()) {
                flag = false;
            } else {
                // 将成功采购的商品进行入库
                PurchaseDetailEntity purchasedDetail = purchaseDetailService.getById(item.getItemId());
                wareSkuService.saveOrUpdateWareSku(purchasedDetail.getSkuId(), purchasedDetail.getWareId(),
                        purchasedDetail.getSkuNum());
            }
            PurchaseDetailEntity purchaseDetail = new PurchaseDetailEntity();
            purchaseDetail.setStatus(item.getStatus());
            purchaseDetail.setId(item.getItemId());
            purchaseDetails.add(purchaseDetail);
        }
        purchaseDetailService.updateBatchById(purchaseDetails);

        // 更新采购单
        PurchaseEntity purchase = new PurchaseEntity();
        purchase.setId(purchaseFinishVO.getId());
        purchase.setStatus(flag ? PurchaseEnum.FINISHED.getCode() : PurchaseEnum.UNUSUAL.getCode());
        this.updateById(purchase);
    }
}